// 组件: zj-select-complex 复杂选择器 (左侧弹出)
// ==================== 参数 ====================
// ※ value ==> 当前值
// ※ model ==> 双向绑定时父组件的键名
// ※ options ==> 数据列表 (默认: [])
// ※ valKey ==> 当数据列表为 Object Array 时, 当前值的键名 (默认: 'id')
// ※ labKey ==> 当数据列表为 Object Array 时, 显示值的键名 (默认: 'name')
// ※ placeholder ==> 提示文字 (默认: '请选择')
// ※ clearable ==> 是否可清除 (默认: true)
// ※ disabled ==> 是否禁用 (默认: false)
// ※ data ==> 数据, 仅做传递使用
// ※ error ==> 错误验证(当前值&提示信息 字体变红) (默认: false)
// ==================== 事件 ====================
// ※ bind:model="model(e)" ==> 双向绑定
// ※ bind:change="change(e)" ==> 选择器值改变时
// ※ bind:sure="sure(e)" ==> 确定事件(仅多选可用)
// ※ bind:clear="clear(e)" ==> 清除事件
// ==================== 插槽 slot ====================
// ※ 默认插槽 ==> xxxxx
// ※ xxxxx ==> xxxxx
// ==================== 方法 ====================
// ※ xxxxx ==> xxxxx

Component({
  properties: {
    value: { // 当前值
      type: String
    },
    model: { // 双向绑定时父组件的键名
      type: String
    },
    options: { // 数据列表
      type: Array,
      value: []
    },
    valKey: { // 当数据列表为 Object Array 时, 当前值的键名
      type: String,
      value: 'id'
    },
    labKey: { // 当数据列表为 Object Array 时, 显示值的键名
      type: String,
      value: 'name'
    },
    placeholder: { // 提示文字
      type: String,
      value: '请选择'
    },
    clearable: { // 是否可清除
      type: Boolean,
      optionalTypes: [String, Number, Boolean],
      value: true
    },
    disabled: { // 是否禁用
      type: Boolean
    },
    data: { // 数据, 仅做传递使用
      type: String, // 没用, 这个设定太弱智了
      optionalTypes: [String, Number, Boolean, Object, Array]
    },
    error: { // 错误验证
      type: Boolean,
      optionalTypes: [String, Number, Boolean],
      value: false
    },
    mutil: { // 是否多选
      type: Boolean,
      optionalTypes: [String, Number, Boolean],
      value: false
    },
    searchKey: { // 搜索内容对应options里的键名，默认为显示值
      type: String
    },
    searchPlaceholder: { // 搜索提示文字
      type: String,
      value: '搜索'
    },
    sideValKey: { // 侧边数据对应options里值的键名
      type: String
    },
    sideLabKey: { // 侧边数据对应options里显示值的键名
      type: String
    }
  },
  data: {
    ind: null, // 当前索引(注: 多选时为[], 与options的length相同)
    multiData: [], // 选择的资产
    // ========== 判断 ==========
    judge_isObj: false, // options[0]是否为object
    judge_placeholderIsShow: false, // placeholder是否显示
    // ========== 弹出层 ==========
    show: false, // 是否显示
    animation: false, // 动效
    searchVal: null, // 搜索框的值
    searchInd: [], // 符合搜索条件的数据索引(注: 与options的length相同)
    // ========== 侧边 ==========
    sideId: 'side_0', // 当下点击的侧边
    sideData: {}
  },
  ready () {},
  observers: {
    // ========== 监听'当前值', 判断placeholder是否显示 ==========
    'value': function (value) {
      let ind = null
      if (this.properties.mutil) { // 多选
        const options = this.properties.options
        const valKey = this.properties.valKey
        ind = this.data.ind && this.data.ind.length ? this.data.ind : []
        ind.length = options.length
        let value_mutil = value ? value.split(',') : []
        options.forEach((b, i) => {
          const val = this.data.judge_isObj ? b[valKey] : b
          const mutilInd = value_mutil.findIndex(b => b + '' === val + '')
          ind[i] = mutilInd !== -1 ? true : false
          mutilInd !== -1 && value_mutil.splice(mutilInd, 1)
        })
        ind = ind.concat(value_mutil)
        // console.log('asdasdsasd', ind)
      } else { // 单选
        ind = this.findIndex(this.properties.value)
      }
      this.setData({
        ind,
        judge_placeholderIsShow: Boolean(!value && value !== 0)
      })
    },
    // ========== 监听'options', options[0]是否为object ==========
    'options': function (options) {
      this.setData({
        judge_isObj: Boolean(typeof(options[0]) === 'object'),
        value: this.properties.value
      })
      // 判断'侧边'是否存在, 获取'侧边'数据
      const sideValKey = this.properties.sideValKey
      const sideLabKey = this.properties.sideLabKey
      if (sideValKey && sideLabKey) {
        let sideData = {}
        for (const i in options) {
          const b = options[i]
          if (sideData[b[sideValKey]] || sideData[b[sideValKey]] === 0) continue
          sideData[b[sideValKey]] = i
        }
        this.setData({ sideData })
      }
    }
  },
  methods: {
    model (e) {
      e = e.detail
      const model = e.currentTarget.dataset.model
      this.setData({ [model]: e.detail.value })
    },
    // ========== 数组找下标 ==========
    findIndex (val, arr) {
      const options = this.properties.options
      const valKey = this.properties.valKey
      let result = null
      if (this.data.judge_isObj) {
        result = options.findIndex(b => b[valKey] === val || b[valKey] + '' === val + '')
      } else {
        result = options.findIndex(b => b === val || b + '' === val + '')
      }
      return result
    },
    // ========== 显示弹出层 ==========
    open () {
      if (this.properties.disabled) return
      this.setData({
        show: true,
        value: this.properties.value
      })
      wx.nextTick(() => { this.setData({ animation: true }) })
    },
    // ========== 关闭弹出层 ==========
    close () {
      this.setData({ animation: false })
      setTimeout(() => {
        this.setData({
          show: false,
          searchVal: null,
          searchInd: []
        })
      }, 300)
    },
    // ========== 搜索时 ==========
    search () {
      const options = this.properties.options
      const searchKey = this.properties.searchKey || this.properties.labKey
      const searchVal = this.properties.searchVal
      let searchInd = []
      searchVal && options.forEach((b, i) => {
        const val = this.data.judge_isObj ? b[searchKey] : b
        searchInd[i] = val.includes(searchVal) ? true : false
      })
      this.setData({ searchInd })
    },
    // ========== 选择器值改变时 ==========
    change (e) {
      const index = e.currentTarget.dataset.index
      const options = this.properties.options
      const valKey = this.properties.valKey
      const judge_isObj = this.data.judge_isObj
      let value = null
      if (this.properties.mutil) { // 多选
        value = []
        this.setData({ [`ind[${index}]`]: !this.data.ind[index] })
        const ind = this.data.ind
        ind.forEach((judge, i) => {
          const val = i >= options.length ? ind[i] : (judge_isObj ? options[i][valKey] : options[i])
          judge && value.push(val)
        })
        value = value.join()
        this.setData({
          multiData: value.split(',')
        })
      } else { // 单选
        this.setData({ ind: index })
        value = judge_isObj ? options[index][valKey] : options[index]
      }
      // 获取当前值
      e.currentTarget.dataset.model = this.properties.model
      e.detail.value = value
      this.triggerEvent('model', e)
      this.triggerEvent('change', e)
      !this.properties.mutil && this.close() // 关闭弹出层
    },
    // ========== 确定 (多选 mutil) ==========
    sure () {
      this.triggerEvent('sure')
      this.close() // 关闭弹出层
    },
    // ========== 取消 ==========
    cancel () {
      if (this.properties.clearable) {
        this.clear()
      } else {
        this.close() // 关闭弹出层
      }
    },
    // ========== 清除 ==========
    clear () {
      this.setData({ isFocus: true })
      const e = {
        currentTarget: { dataset: { model: this.properties.model } },
        detail: { value: this.properties.mutil ? [] : '' }
      }
      this.triggerEvent('model', e)
      this.triggerEvent('change', e)
      this.triggerEvent('clear', e)
      this.close() // 关闭弹出层
    },
    // ========== 删除 (多选 mutil) ==========
    del (e) {
      this.change(e) // 选择器值改变时
    },
    // ========== 侧边点击 ==========
    sideTap (e) {
      const sideId = e.currentTarget.dataset.id
      this.setData({ sideId })
      // console.log('sfsdafsadfa', id)
    }
  }
})
